package org.example.sever;

import jdk.jfr.Frequency;
import org.example.POJO.game.Room;
import org.example.POJO.online.ChatManager;
import org.example.POJO.online.ChatSession;
import org.example.POJO.online.MyMessage;
import org.example.Utils.SocketUtil;
import org.example.Utils.UserFileManager;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

import static org.example.Utils.SocketUtil.send;

public class ChessServer {
    private static Map<String, ServerThread> clients;//保存登录的所有客户端线程
    //发起者
    public static String fightFrom;
    //被挑战者
    public static String fightTo;

    //聊天池
    public static ChatManager chatManager = new ChatManager();

    //房间池
    public static Vector<Room> rooms = new Vector<>();

    public static void main(String[] args) {
        new ChessServer().start();
    }

    public void start() {
        try {

            ServerSocket serverSocket = new ServerSocket(8888);
            clients = new HashMap<>();
            System.out.println("服务端——启动成功");
            //给房间池充满15个房间
            for (int i = 0; i < 15; i++) {
                Room room = new Room("room" + (i + 1));
                rooms.add(room);
            }
            System.out.println("房间池准备就绪");
            while (true) {
                Socket accept = serverSocket.accept();
                ServerThread serverThread = new ServerThread(accept);
                serverThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static class ServerThread extends Thread {
        private Socket socket;

        private String username; // 当前线程绑定的用户名

        public ServerThread(Socket socket) {
            this.socket = socket;
        }

        public Socket getSocket() {
            return socket;
        }

        @Override
        public void run() {
            try {
                while (!socket.isClosed()) { // 确保socket未关闭时继续处理
                    Object receive = null; // 接收客户端消息
                    receive = SocketUtil.receive(socket);

                    if (receive == null) {
                        throw new IOException("接收到空数据，可能客户端已断开连接");
                    }
                    System.out.println(receive);
                    if (receive instanceof MyMessage) {
                        MyMessage request = (MyMessage) receive;
                        switch (request.getType()) {
                            case CONNECT:
                                login(request);
                                break;
                            case LIST:
                                list();
                                break;
                            case FIGHT:
                                //发送对战请求
                                fight(request);
                                break;
                            case FIGHT_SUCCESS:
                                fightSuccess(request);
                                break;
                            case FIGHT_DEFEAT:
                                fightDefeat(request);
                                break;
                            case MOVE:
                                move(request);
                                break;
                            case EAT:
                                eat(request);
                                break;
                            case BACK:
                                back(request);
                                break;
                            case PEACE:
                                peace(request);
                                break;
                            case PEACE_SUCCESS:
                                peaceSuccess(request);
                                break;
                            case PEACE_DEFEAT:
                                peaceDefeat(request);
                                break;
                            case DEFEAT:
                                defeat(request);
                                break;
                            case CHAT:
                                chat(request);
                                break;
                            case JOIN:
                                joinRoom(request);
                            default:
                                break;
                        }
                    }
                }
            } catch (IOException e) {
                // 针对Socket异常处理，避免死循环
                System.out.println("客户端连接异常或断开: " + username + "，错误: " + e.getMessage());
            } finally {
                cleanup(); // 调用清理方法
            }
        }

        //加入房间
        private void joinRoom(MyMessage request) {
            UserFileManager userFileManager = new UserFileManager();
            String username = request.getFrom();
            String roomId = request.getContent().toString();
            //向房间池里添加房间
            Room room = getRoom(roomId);
            room.addPlayer(username);
            room.setLeftAvatar(userFileManager.getAvatar(username));
            if (room.getPlaycount() == 2) {
                //发信息给两个用户
                room.setRightAvatar(userFileManager.getAvatar(room.getUsers()[1]));
                room.setLeftAvatar(userFileManager.getAvatar(room.getUsers()[0]));
                String fromUser = room.getUsers()[0];
                String toUser = room.getUsers()[1];

                MyMessage respone = new MyMessage();
                respone.setType(MyMessage.Type.JOIN);
                respone.setContent(rooms);
                clients.forEach((k, v) -> {
                    try {
                        send(v.getSocket(), respone);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });

                MyMessage resp = new MyMessage();
                //发送信息给两个用户
                resp.setType(MyMessage.Type.FIGHT_SUCCESS);
                resp.setFrom(fromUser);
                resp.setTo(toUser);
                resp.setFromCamp(1); // 设置发送者的阵营标识
                resp.setToCamp(0); // 设置接收者的阵营标识
                resp.setContent(request.getContent());
                try {
                    send(clients.get(fromUser).getSocket(), resp);
                    send(clients.get(toUser).getSocket(), resp);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            } else if (room.getPlaycount() == 1) {
                //发信息给线程里的客户端
                room.setLeftAvatar(userFileManager.getAvatar(username));
                MyMessage resp = new MyMessage();
                resp.setType(MyMessage.Type.JOIN);
                resp.setContent(rooms);
                clients.forEach((k, v) -> {
                    try {
                        send(v.getSocket(), resp);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
            }
        }

        //用户名返回房间号
        private String getRoomId(String username) {
            for (Room room : rooms) {
                if (room.getUsers()[0].equals(username) || room.getUsers()[1].equals(username)) {
                    return room.getRoomId();
                }
            }
            return null;
        }
        //根据房间号返回房间
        private Room getRoom(String roomId) {
            for (Room room : rooms) {
                if (room.getRoomId().equals(roomId)) {
                    return room;
                }
            }
            return null;
        }

        // 添加清理方法，便于代码复用
        private void cleanup() {
            if (username != null) {
                clients.remove(username); // 移除客户端
                //清除用户文件记录
                UserFileManager userFileManager = new UserFileManager();
                userFileManager.deleteUser(username);
                System.out.println("玩家:" + username + "下线");

                // 通知其他客户端此用户已下线
                MyMessage offlineMessage = new MyMessage();
                offlineMessage.setType(MyMessage.Type.SUCCESS); // 假设 DISCONNECT 表示用户下线通知
                offlineMessage.setContent(getUsername()); // 设置下线消息内容

                // 广播消息给其他客户端
                clients.forEach((k, v) -> {
                    if (!k.equals(username)) { // 不发送给下线服务器
                        try {
                            send(v.getSocket(), offlineMessage);
                        } catch (IOException e) {
                            System.err.println("通知客户端失败: " + k);
                            e.printStackTrace();
                        }
                    }
                });
            }

            try {
                if (socket != null && !socket.isClosed()) {
                    socket.close(); // 关闭Socket
                    System.out.println("Socket连接已关闭: " + username);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        private void login(MyMessage message) {
            username = message.getFrom(); // 获取用户名并绑定线程
            clients.put(username, this);  // 将客户端线程加入到 clients 中
            System.out.println("客户端连接: " + username);

            // 发送登录成功消息
            MyMessage response = new MyMessage();
            response.setType(MyMessage.Type.SUCCESS);
            try {
                send(socket, response);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //List的方法
        private void list() {
            MyMessage resp = new MyMessage();
            resp.setType(MyMessage.Type.SUCCESS);
            resp.setContent(getUsername());
            clients.forEach((k, v) -> {
                try {
                    send(v.getSocket(), resp);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }

        private Vector getUsername() {
            //对内容进行序列化
            Vector<String> list = new Vector<>();
            Set<String> keySets = clients.keySet();
            Iterator<String> iterator = keySets.iterator();
            while (iterator.hasNext()) {
                list.add(iterator.next());
            }
            return list.size() == 0 ? null : list;
        }

        // 发送响应消息的通用方法
        private void sendResponse(MyMessage request, MyMessage.Type type, String from, String to) {
            ServerThread fromSocket = clients.get(from);
            ServerThread toSocket = clients.get(to);

            MyMessage resp = new MyMessage();
            resp.setFrom(from); // 设置消息的发送者
            resp.setTo(to); // 设置消息的接收者
            resp.setFromCamp(1); // 设置发送者的阵营标识
            resp.setToCamp(0); // 设置接收者的阵营标识
            resp.setType(type); // 设置消息类型
            resp.setContent(request.getContent()); // 设置消息内容

            try {
                send(toSocket.getSocket(), resp);

                if (type == MyMessage.Type.FIGHT_SUCCESS || type == MyMessage.Type.CHAT) {
                    send(fromSocket.getSocket(), resp);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        // 聊天发送处理
        private void chat(MyMessage request) {
            // 创建聊天绑定（如果还不存在）
            chatManager.createChatBinding(request.getFrom(), request.getTo());

            // 获取对应的聊天会话
            ChatSession userChat = chatManager.getChatSession(request.getFrom(), request.getTo());

            if (userChat != null) {
                // 如果聊天会话存在，则添加新消息并更新聊天历史
                userChat.addMessage(request.getFrom(), request.getContent());

                // 获取最新的聊天历史
                String chatHistory = chatManager.getChatHistory(request.getFrom(), request.getTo());

                // 更新请求的内容为最新的聊天历史
                request.setContent(chatHistory);

                // 发送响应
                sendResponse(request, MyMessage.Type.CHAT, request.getFrom(), request.getTo());
            } else {
                System.err.println("未能找到聊天会话: " + request.getFrom() + "-" + request.getTo());
            }
        }

        // 战斗胜利处理
        private void fightSuccess(MyMessage request) {
            sendResponse(request, MyMessage.Type.FIGHT_SUCCESS, fightFrom, fightTo);
        }

        // 对方逃跑处理
        private void fightDefeat(MyMessage request) {
            sendResponse(request, MyMessage.Type.FIGHT_DEFEAT, request.getFrom(), request.getTo());
        }

        // 求和成功处理
        private void peaceSuccess(MyMessage request) {
            sendResponse(request, MyMessage.Type.PEACE_SUCCESS, request.getFrom(), request.getTo());
        }

        // 认输处理
        private void defeat(MyMessage request) {
            sendResponse(request, MyMessage.Type.DEFEAT, request.getFrom(), request.getTo());
            MyMessage resp = new MyMessage();
            resp.setFrom(request.getFrom());
            resp.setTo(request.getTo());
            String roomId = getRoomId(request.getFrom());
            Room room = getRoom(roomId);
            //重置改房间
            room.clear();
        }

        // 和平失败处理
        private void peaceDefeat(MyMessage request) {
            sendResponse(request, MyMessage.Type.PEACE_DEFEAT, request.getFrom(), request.getTo());
        }

        // 求和请求处理
        private void peace(MyMessage request) {
            sendResponse(request, MyMessage.Type.PEACE, request.getFrom(), request.getTo());
        }

        // 回退请求处理
        private void back(MyMessage request) {
            sendResponse(request, MyMessage.Type.BACK, request.getFrom(), request.getTo());
        }

        // 吃子动作处理
        private void eat(MyMessage request) {
            sendResponse(request, MyMessage.Type.EAT, request.getFrom(), request.getTo());
        }

        // 移动动作处理
        private void move(MyMessage request) {
            sendResponse(request, MyMessage.Type.MOVE, request.getFrom(), request.getTo());
        }

        // 战斗请求处理
        private void fight(MyMessage request) {
            fightFrom = request.getFrom(); // 保存战斗发起者的ID
            fightTo = request.getTo(); // 保存战斗目标的ID
            sendResponse(request, MyMessage.Type.FIGHT, request.getFrom(), request.getTo());
        }

    }
}

